#include "HuoYueDuPart.h"
#include "Player.h"
#include "PlayerMgr.h"
#include "Common/Utility/TimeUtility.h"
#include "Common/TableData/HuoyueduActiveCfg.h"
#include "Common/TableData/HuoyueduRewardCfg.h"
#include "OperateLimitPart.h"
#include "drop/DropMgr.h"

using namespace ProtoBuf;

HuoYueDuPart::HuoYueDuPart()
{
	m_HuoYueDuRecord.clear();
}

HuoYueDuPart::~HuoYueDuPart()
{
	m_HuoYueDuRecord.clear();
}

bool HuoYueDuPart::SaveDB(CharacterDBInfo& characterDB)
{
	characterDB.clear_huoyuedudata();
	CharacterDBHuoYueDuInfo* pHuoYueDuInfo = characterDB.mutable_huoyuedudata();
	for (HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin(); iter != m_HuoYueDuRecord.end(); ++iter)
	{
		CharacterDBSingleHuoYueDuInfoInfo* pSingleHuoYueDuInfo = pHuoYueDuInfo->add_huoyueduinfo();
		pSingleHuoYueDuInfo->set_type(iter->first);
		pSingleHuoYueDuInfo->set_value(iter->second.val);
		pSingleHuoYueDuInfo->set_time(iter->second.time);
	}

	return true;
}

bool HuoYueDuPart::Init(Creature *pMaster, uint32_t partType, CharacterDBInfo* pCharacterDB /* = nullptr */)
{
	Part::Init(pMaster, partType);

	uint32_t nNowTime = Time::Now().UnixSec();

	const CharacterDBHuoYueDuInfo& huoYueDuInfo = pCharacterDB->huoyuedudata();
	for (int32_t i = 0; i < huoYueDuInfo.huoyueduinfo_size(); i++)
	{
		const CharacterDBSingleHuoYueDuInfoInfo& singleHuoYueDuInfo = huoYueDuInfo.huoyueduinfo(i);
		
		if (singleHuoYueDuInfo.type() >= HYDT_MAX)
		{
			MMOLOG_FMT_ERROR("[logic] HuoYueDuPart::Init but type >= PRSTE_MAX...type=%d", singleHuoYueDuInfo.type());
			continue;
		}

		const HuoyueduActiveCfgInfo* pActiveCfgInfo = g_GetHuoyueduActiveCfgTable()->GetHuoyueduActiveCfgInfo(singleHuoYueDuInfo.type());
		if (nullptr == pActiveCfgInfo)
		{
			continue;
		}

		//按天刷新的
		if (pActiveCfgInfo->cycle == HYDUT_UPDATE_DAILY)
		{
			if (TimeUtility::CheckDayUpdate(nNowTime, singleHuoYueDuInfo.time()))
			{
				continue;
			}
		}

		//按周刷新的
		if (pActiveCfgInfo->cycle == HYDUT_UPDATE_WEEK)
		{
			if (TimeUtility::CheckWeekUpdate(nNowTime, singleHuoYueDuInfo.time()))
			{
				continue;
			}
		}

		CHuoYueDuInfo info;
		info.type = singleHuoYueDuInfo.type();
		info.val = singleHuoYueDuInfo.value();
		info.time = singleHuoYueDuInfo.time();
		m_HuoYueDuRecord[info.type] = info;
	}

	//InitHuoYueDuData();

	return true;
}

void HuoYueDuPart::InitHuoYueDuData()
{
	VEC_INT32 clearVec;
	uint32_t nNowTime = Time::Now().UnixSec();
	for (HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin(); iter != m_HuoYueDuRecord.end(); ++iter)
	{
		const HuoyueduActiveCfgInfo* pActiveCfgInfo = g_GetHuoyueduActiveCfgTable()->GetHuoyueduActiveCfgInfo(iter->first);
		if (nullptr == pActiveCfgInfo)
		{
			continue;
		}

		//按天刷新的
		if (pActiveCfgInfo->cycle == HYDUT_UPDATE_DAILY)
		{
			if (TimeUtility::CheckDayUpdate(nNowTime, iter->second.time))
			{
				clearVec.push_back(iter->first);
			}
		}

		//按周刷新的
		if (pActiveCfgInfo->cycle == HYDUT_UPDATE_WEEK)
		{
			if (TimeUtility::CheckWeekUpdate(nNowTime, iter->second.time))
			{
				clearVec.push_back(iter->first);
			}
		}
	}

	for (uint32_t i = 0; i < clearVec.size(); i++)
	{
		m_HuoYueDuRecord.erase(clearVec[i]);
	}
}

bool HuoYueDuPart::UnInit()
{
	return true;
}

bool HuoYueDuPart::DailyUpdate(uint64_t unixSec)
{
	VEC_INT32 clearVec;
	for (HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin(); iter != m_HuoYueDuRecord.end(); ++iter)
	{
		const HuoyueduActiveCfgInfo* pActiveCfgInfo = g_GetHuoyueduActiveCfgTable()->GetHuoyueduActiveCfgInfo(iter->first);
		if (nullptr == pActiveCfgInfo)
		{
			continue;
		}

		//按天刷新的
		if (pActiveCfgInfo->cycle == HYDUT_UPDATE_DAILY)
		{
			clearVec.push_back(iter->first);
		}
	}

	for (uint32_t i = 0; i < clearVec.size(); i++)
	{
		m_HuoYueDuRecord.erase(clearVec[i]);
	}

	return true;
}

bool HuoYueDuPart::WeekUpdate(uint64_t unixSec)
{
	VEC_INT32 clearVec;
	for (HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin(); iter != m_HuoYueDuRecord.end(); ++iter)
	{
		const HuoyueduActiveCfgInfo* pActiveCfgInfo = g_GetHuoyueduActiveCfgTable()->GetHuoyueduActiveCfgInfo(iter->first);
		if (nullptr == pActiveCfgInfo)
		{
			continue;
		}

		//按周刷新的
		if (pActiveCfgInfo->cycle == HYDUT_UPDATE_WEEK)
		{
			clearVec.push_back(iter->first);
		}
	}

	for (uint32_t i = 0; i < clearVec.size(); i++)
	{
		m_HuoYueDuRecord.erase(clearVec[i]);
	}
	return true;
}

void HuoYueDuPart::AddHuoYueDuRecord(uint32_t type)
{
	if (nullptr == m_pMaster)
	{
		return;
	}

	OperateLimitPart* pOperateLimitPart = dynamic_cast<OperateLimitPart*>(m_pMaster->GetPart(PART_OPERATELIMIT));
	if (nullptr == pOperateLimitPart)
	{
		return;
	}

	const HuoyueduActiveCfgInfo* pActiveCfgInfo = g_GetHuoyueduActiveCfgTable()->GetHuoyueduActiveCfgInfo(type);
	if (nullptr == pActiveCfgInfo)
	{
		return;
	}

	HuoYueDuMap::iterator iter = m_HuoYueDuRecord.find(type);
	if (iter == m_HuoYueDuRecord.end())
	{
		CHuoYueDuInfo info;
		info.type = type;
		info.val = 1;
		info.time = Time::Now().sec();
		m_HuoYueDuRecord[type] = info;
	}
	else
	{
		//次数进行累加1
		iter->second.val++;

		if (iter->second.val > (uint32_t)pActiveCfgInfo->number)
		{
			return;
		}
	}

	pOperateLimitPart->AddOprateLimit(PRSTE_HUOYUEDU, pActiveCfgInfo->eachScore);

	SendHuoYueDuInfo();
}

void HuoYueDuPart::SendHuoYueDuInfo()
{
	if (nullptr == m_pMaster)
	{
		return;
	}

	OperateLimitPart* pOperateLimitPart = dynamic_cast<OperateLimitPart*>(m_pMaster->GetPart(PART_OPERATELIMIT));
	if (nullptr == pOperateLimitPart)
	{
		return;
	}

	HuoYueDuUpdateNotify notify;
	HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin();
	for (; iter != m_HuoYueDuRecord.end(); ++iter)
	{
		HuoYueDuInfo* pHuoYueDuInfo = notify.add_huoyueduinfo();
		pHuoYueDuInfo->set_type(iter->first);
		pHuoYueDuInfo->set_process(iter->second.val);
	}

	notify.set_huoyuedu(pOperateLimitPart->GetOprateLimit(PRSTE_HUOYUEDU));

	m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_UPDATE_NOTIFY, &notify);
}

//uint32_t HuoYueDuPart::CalculateHuoYueDu()
//{
//	uint32_t allScore = 0;
//	//累计完成的所有活跃度的值
//	HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin();
//	for (; iter != m_HuoYueDuRecord.end(); ++iter)
//	{
//		const HuoyueduActiveCfgInfo* pActiveCfgInfo = g_GetHuoyueduActiveCfgTable()->GetHuoyueduActiveCfgInfo(iter->first);
//		if (nullptr == pActiveCfgInfo)
//		{
//			continue;
//		}
//
//		if (iter->second.val >= (uint32_t)pActiveCfgInfo->number && !iter->second.isCalcu)
//		{
//			allScore += pActiveCfgInfo->eachScore;
//			iter->second.isCalcu = true;
//		}
//	}
//
//	return allScore;
//}

bool HuoYueDuPart::OnMsgHandle(uint32_t cmd, const char* data, uint32_t len)
{
	switch (cmd)
	{
	case CLIENT_TO_LOGIC_HUOYUEDU_INFO:
	{
		HandleHuoYueDuInfo(data, len);
		break;
	}
	case CLIENT_TO_LOGIC_HUOYUEDU_REWARD:
	{
		HandleHuoYueDuReward(data, len);
		break;
	}
	default:
		break;
	}
	return true;
}

bool HuoYueDuPart::HandleHuoYueDuInfo(const char* data, uint32_t len)
{
	CGHuoYueDuInfoReq huoYueDuInfoReq;
	GCHuoYueDuInfoRsp huoYueDuInfoRsp;

	if (!huoYueDuInfoReq.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] WelfarePart::HandleHuoYueDuInfo CGHuoYueDuInfoReq parse failed...");
		return false;
	}

	if (nullptr == m_pMaster)
	{
		return false;
	}

	OperateLimitPart* pOperateLimitPart = dynamic_cast<OperateLimitPart*>(m_pMaster->GetPart(PART_OPERATELIMIT));
	if (nullptr == pOperateLimitPart)
	{
		return false;
	}

	//填充活跃度进度
	HuoYueDuMap::iterator iter = m_HuoYueDuRecord.begin();
	for (; iter != m_HuoYueDuRecord.end(); ++iter)
	{
		HuoYueDuInfo* pHuoYueDuInfo = huoYueDuInfoRsp.add_huoyueduinfo();
		pHuoYueDuInfo->set_type(iter->first);
		pHuoYueDuInfo->set_process(iter->second.val);
	}

	//填充领取宝箱进度
	huoYueDuInfoRsp.set_rewardbit(pOperateLimitPart->GetOprateLimit(PRSTE_HUOYUEDU_REWARD));

	//填充活跃度值
	huoYueDuInfoRsp.set_huoyuedu(pOperateLimitPart->GetOprateLimit(PRSTE_HUOYUEDU));

	m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_INFO, &huoYueDuInfoRsp);

	return true;
}

bool HuoYueDuPart::HandleHuoYueDuReward(const char* data, uint32_t len)
{
	CGHuoYueDuRewardReq huoYueDuRewardReq;
	GCHuoYueDuRewardRsp huoYueDuRewardRsp;

	if (!huoYueDuRewardReq.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] WelfarePart::HandleHuoYueDuReward CGHuoYueDuRewardReq parse failed...");
		return false;
	}

	OperateLimitPart* pOperateLimitPart = dynamic_cast<OperateLimitPart*>(m_pMaster->GetPart(PART_OPERATELIMIT));
	if (nullptr == pOperateLimitPart)
	{
		return false;
	}

	uint32_t index = huoYueDuRewardReq.index();
	uint32_t huoYueDuReward = pOperateLimitPart->GetOprateLimit(PRSTE_HUOYUEDU_REWARD);
	uint32_t NewHuoYueDuReward = huoYueDuReward | (1 << index);
	//已经领取过该奖励了
	if (NewHuoYueDuReward == huoYueDuReward)
	{
		huoYueDuRewardRsp.set_ret(RET_HUOYUEDU_HAVE_REWARD);
		m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_REWARD, &huoYueDuRewardRsp);
		return false;
	}
	
	//配置表出错
	const HuoyueduRewardCfgInfo* pRewardCfgInfp = g_GetHuoyueduRewardCfgTable()->GetHuoyueduRewardCfgInfo(index);
	if (nullptr == pRewardCfgInfp)
	{
		huoYueDuRewardRsp.set_ret(RET_DATA_ERROR);
		m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_REWARD, &huoYueDuRewardRsp);
		return false;
	}

	uint32_t allScore = pOperateLimitPart->GetOprateLimit(PRSTE_HUOYUEDU);

	//活跃度值不够
	if (allScore < (uint32_t)pRewardCfgInfp->activeScore)
	{
		huoYueDuRewardRsp.set_ret(RET_HUOYUEDU_SCORE_LIMIT);
		m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_REWARD, &huoYueDuRewardRsp);
		return false;
	}
	Player *pPlayer = dynamic_cast<Player*>(m_pMaster);
	if (nullptr == pPlayer)
	{
		LogErrFmtPrint("[logic] HuoYueDuPart::HandleHuoYueDuReward....nullptr == pPlayer..");
		return false;
	}
	VEC_INT32 vecBox;
	vecBox.push_back(pRewardCfgInfp->rewardId);
	SItemSourceParam sourceParam;
	int32_t ret = g_GetDropMgr()->PlayerAddBox(pPlayer, vecBox, sourceParam);
	if (RET_SUCCESS != ret)
	{
		huoYueDuRewardRsp.set_ret(ret);
		m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_REWARD, &huoYueDuRewardRsp);
		return false;

	}

	pOperateLimitPart->SetOprateLimit(PRSTE_HUOYUEDU_REWARD, NewHuoYueDuReward);

	huoYueDuRewardRsp.set_ret(RET_SUCCESS);
	m_pMaster->SendDataToClientEx(EMODULE_ID_HUOYUEDU, LOGIC_TO_CLIENT_HUOYUEDU_REWARD, &huoYueDuRewardRsp);
	return false;

	return true;

}